﻿using DocumentFormat.OpenXml.Drawing;
using Magicodes.ExporterAndImporter.Core;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using MT.Enterprise.Utils.Extensions;
using Newtonsoft.Json;
using Nito.AsyncEx.Synchronous;
using NP.BPMReportPlatform.AnalysisInstance.Dtos;
using NP.BPMReportPlatform.AuthorizationUserManager.Dtos;
using NP.BPMReportPlatform.DBHelper;
using NP.BPMReportPlatform.Entities.BPM_Engine;
using NP.BPMReportPlatform.Entities.BPM_Process;
using NP.BPMReportPlatform.Entities.NIP_WorkFlow;
using NP.BPMReportPlatform.Reports.CommonApprovalProcessReport.Dtos;
using NP.BPMReportPlatform.Utilities;
using NP.Enterprise.Utils.Extension;
using NPOI.HSSF.Record;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using RestSharp.Extensions;
using SqlSugar;
using SqlSugar.Extensions;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using static Org.BouncyCastle.Math.EC.ECCurve;

namespace NP.BPMReportPlatform.AnalysisInstance
{
    public class AnalysisInstanceService : BPMReportPlatformAppService, IAnalysisInstanceService
    {
        private readonly SqlSugarClient _dbProcess, _dbEngine;
        private readonly string _pcUrl;
        private readonly IConfiguration _configuration;
        public AnalysisInstanceService(ISqlSugarAppService sqlSugarAppService, IConfiguration configuration)
        {
            _dbProcess = sqlSugarAppService.GetProcessInstance();
            _dbEngine = sqlSugarAppService.GetEngineInstance();
            _configuration = configuration;
            _pcUrl = _configuration["BPM:NoAuthPCProcessUrl"];
        }

        public async Task<PagedResultDto<Dictionary<string, object>>> GetAnalysisInstances(AnalysisInstanceQueryDto searchDto)
        {
            var status = new List<int>();
            var result = new PagedResultDto<Dictionary<string, object>>();

            if (searchDto.InstanceStatus.HasValue)
            {
                status = ConvertToInstnaceStatus(searchDto.InstanceStatus.Value);
            }

            searchDto.OrderStatus.ForEach(s =>
            {
                if (s.HasValue)
                {
                    status.AddRange(ConvertToInstnaceStatus(s.Value));
                }
            });

            bool isAdmin = false;
            if (!searchDto.processCodes.Any())
            {
                isAdmin = await CheckIsAdmin();
                if (!isAdmin)
                {
                    searchDto.processCodes = await GetAllAuthProcessCodes();
                }
            }

            if ((string.IsNullOrWhiteSpace(searchDto.InstanceStartTime) || string.IsNullOrWhiteSpace(searchDto.InstanceEndTime))
                && string.IsNullOrWhiteSpace(searchDto.InstanceNumber))
            {
                searchDto.InstanceStartTime = DateTime.Today.AddMonths(-1).ToString(DateFormatHelper.DateTimeFormat);
                searchDto.InstanceEndTime = DateTime.Today.AddDays(1).AddSeconds(-1).ToString(DateFormatHelper.DateTimeFormat);
            }
            else
            {
                if (searchDto.processCodes == null || searchDto.processCodes.Count != 1)
                {
                    var stime = searchDto.InstanceStartTime.ToOurDateTime();
                    var etime = searchDto.InstanceEndTime.ToOurDateTime();
                    if (etime.Subtract(stime).TotalDays > 32)
                    {
                        throw new Exception(searchDto.IsAll ? "最多导出一个月的数据（导出单个流程不做时间限制）" : "最多查询一个月的数据（查询单个流程不做时间限制）");
                    }
                }
            }

            RefAsync<int> count = 0;
            var instanceDataWhereQuery = _dbEngine.Queryable<Instances, InstanceStates>((a, b) => a.InstanceId == b.InstanceId)
            .OrderBy((a, b) => b.StartTime, OrderByType.Desc)
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.InstanceNumber), a => a.Number == searchDto.InstanceNumber)
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.InstanceTopic), a => a.Topic.Contains(searchDto.InstanceTopic))
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.ProcessName), a => a.ProcessName.Contains(searchDto.ProcessName))
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.StartUserName), a => a.StartUserName == searchDto.StartUserName)
            .WhereIF(searchDto.ProcessId.HasValue, (a, b) => a.ProcessId == searchDto.ProcessId)
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.InstanceStartTime), (a, b) => b.StartTime >= searchDto.InstanceStartTime.ToOurDateTime())
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.InstanceEndTime), (a, b) => b.StartTime <= searchDto.InstanceEndTime.ToOurDateTime())
            .WhereIF(status.Count > 0, (a, b) => SqlFunc.ContainsArray(status, b.Status))
            .WhereIF(searchDto.processCodes.Any() && isAdmin || !isAdmin, a => SqlFunc.ContainsArray(searchDto.processCodes, a.BTID));

            var instanceDataQuery = instanceDataWhereQuery.Select((a, b) => new AnalysisInstanceResultDto
            {
                InstanceId = a.InstanceId,
                InstanceNumber = a.Number,
                InstanceTopic = a.Topic,
                InstanceStatus = b.Status,
                InstanceStatusName = b.StatusName,
                InstanceUserName = a.StartUserName,
                InstanceStartTime = b.StartTime,
                InstanceEndTime = b.LatestArriveTime,
                ProcessName = a.ProcessName,
            });

            var instanceData = await instanceDataQuery.ToPageListAsync(searchDto.PageIndex, searchDto.PageSize, count);
            result.TotalCount = count;

            var instanceIds = instanceData.Select(s => s.InstanceId).ToList();
            var activityData = await _dbEngine.Queryable<Activities, Tasks>((a, b) => new object[]
               {
                 JoinType.Left, a.ActivityId.ToString() == b.ActivityId
               }).Where(a => instanceIds.Contains(a.InstanceId))
               .OrderBy(a => a.Order)
                .Select((a, b) => new ActivitieTaskModel
                {
                    InstanceId = a.InstanceId,
                    InstanceNumber = a.InstanceNumber,
                    Name = a.Name,
                    ArriveTime = a.ArriveTime,
                    ElapsedTime = a.ElapsedTime,
                    FinishTime = a.FinishTime,
                    UserName = b.UserName,
                    GrandNodeId = a.GrandNodeId,
                    ActivityId = a.ActivityId,
                    UserId = b.UserId,
                    Status = b.Status,
                }).ToListAsync();

            var activityDataDic = activityData.GroupBy(x => x.InstanceId).ToDictionary(x => x.Key, x => x);

            var dicList = new ConcurrentBag<Dictionary<string, object>>();
            Parallel.ForEach(instanceData, new ParallelOptions() { MaxDegreeOfParallelism = 2 }, (item, _) =>
            {
                if (item.InstanceStatus != (int)TaskCommonStatus.Done
                    && item.InstanceStatus != (int)TaskCommonStatus.Refused
                    && item.InstanceStatus != (int)TaskCommonStatus.Canceled)
                {
                    item.InstanceEndTime = null;
                }

                var activities = activityDataDic.Where(x => x.Key == item.InstanceId)
                    .SelectMany(x => x.Value.ToList())
                    .GroupBy(b => new { b.InstanceId, b.Name, b.GrandNodeId })
                    .ToDictionary(k => k.Key, v => v.ToList());

                var flag = 1;
                if (item.InstanceEndTime != null)
                {
                    item.ElapsedTime = TransferHour((item.InstanceEndTime.Value - item.InstanceStartTime.Value).TotalSeconds);
                }

                var dic = new Dictionary<string, object>(item.ToOurJsonString().ToOurObject<Dictionary<string, object>>(), StringComparer.OrdinalIgnoreCase);
                foreach (var activity in activities)
                {
                    if (activity.Key.Name == "开始")
                    {
                        continue;
                    }
                    dic.Add($"node{flag}_name", activity.Key.Name);
                    if (activity.Value.Count > 0)
                    {
                        dic.Add($"node{flag}_time", TransferHour(activity.Value.GroupBy(f => f.ActivityId)
                            .Select(f => f.First().ElapsedTime).Sum()));
                        dic.Add($"node{flag}_user", string.Join("; ", activity.Value.Select(s => s.UserName).Distinct()));
                        dic.Add($"node{flag}_userId", string.Join("; ", activity.Value.Select(s => s.UserId).Distinct()));
                        dic.Add($"node{flag}_userList", activity.Value.Select(s => new { s.UserId, s.UserName }).Distinct());

                        if (activity.Value.Any(x => x.Status == (int)InstanceQueryStatus.Processing))
                        {
                            dic.AddOrUpdate("currentNode", activity.Key.Name);
                            dic.AddOrUpdate("currentApprover", string.Join("; ", activity.Value.Select(s => s.UserName).Distinct()));
                        }
                    }

                    flag++;
                }

                if (dic.ContainsKey("nodeCount"))
                {
                    dic["nodeCount"] = flag - 1;
                }

                dic.AddOrUpdate("Url", string.Format(_pcUrl, item.InstanceNumber));

                dicList.Add(dic);
            });

            return new PagedResultDto<Dictionary<string, object>>
            {
                Items = dicList.ToList().OrderByDescending(x => x["instanceStartTime"]).ToList(),
                TotalCount = count,
            };
        }

        private async Task<List<Dictionary<string, object>>> GetAnalysisInstances_All(AnalysisInstanceQueryDto searchDto)
        {
            var status = new List<int>();
            var result = new List<Dictionary<string, object>>();

            if (searchDto.InstanceStatus.HasValue)
            {
                status = ConvertToInstnaceStatus(searchDto.InstanceStatus.Value);
            }

            searchDto.OrderStatus.ForEach(s =>
            {
                if (s.HasValue)
                {
                    status.AddRange(ConvertToInstnaceStatus(s.Value));
                }
            });

            bool isAdmin = false;
            if (!searchDto.processCodes.Any())
            {
                isAdmin = await CheckIsAdmin();
                if (!isAdmin)
                {
                    searchDto.processCodes = await GetAllAuthProcessCodes();
                }
            }

            if ((string.IsNullOrWhiteSpace(searchDto.InstanceStartTime) || string.IsNullOrWhiteSpace(searchDto.InstanceEndTime)) &&
                string.IsNullOrWhiteSpace(searchDto.InstanceNumber))
            {
                searchDto.InstanceStartTime = DateTime.Today.AddMonths(-1).ToString(DateFormatHelper.DateTimeFormat);
                searchDto.InstanceEndTime = DateTime.Today.AddDays(1).AddSeconds(-1).ToString(DateFormatHelper.DateTimeFormat);
            }
            else
            {
                if (searchDto.processCodes == null || searchDto.processCodes.Count != 1)
                {
                    var stime = searchDto.InstanceStartTime.ToOurDateTime();
                    var etime = searchDto.InstanceEndTime.ToOurDateTime();
                    var sss = etime.Subtract(stime).TotalDays;
                    if (etime.Subtract(stime).TotalDays > 32)
                    {
                        throw new Exception(searchDto.IsAll ? "最多导出一个月的数据（导出单个流程不做时间限制）" : "最多查询一个月的数据（查询单个流程不做时间限制）");
                    }
                }
            }

            RefAsync<int> count = 0;
            var instanceDataWhereQuery = _dbEngine.Queryable<Instances, InstanceStates, Activities, Tasks>(
                (a, b, c, d) => new JoinQueryInfos(JoinType.Inner, a.InstanceId == b.InstanceId, 
                JoinType.Inner, a.InstanceId == c.InstanceId,
                JoinType.Left, c.ActivityId.ToString() == d.ActivityId))
            .OrderBy((a, b) => b.StartTime, OrderByType.Desc)
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.InstanceNumber), a => a.Number == searchDto.InstanceNumber)
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.InstanceTopic), a => a.Topic.Contains(searchDto.InstanceTopic))
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.ProcessName), a => a.ProcessName.Contains(searchDto.ProcessName))
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.StartUserName), a => a.StartUserName == searchDto.StartUserName)
            .WhereIF(searchDto.ProcessId.HasValue, (a, b) => a.ProcessId == searchDto.ProcessId)
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.InstanceStartTime), (a, b) => b.StartTime >= searchDto.InstanceStartTime.ToOurDateTime())
            .WhereIF(!string.IsNullOrWhiteSpace(searchDto.InstanceEndTime), (a, b) => b.StartTime <= searchDto.InstanceEndTime.ToOurDateTime())
            .WhereIF(status.Count > 0, (a, b) => SqlFunc.ContainsArray(status, b.Status))
            .WhereIF(searchDto.processCodes.Any() && isAdmin || !isAdmin, a => SqlFunc.ContainsArray(searchDto.processCodes, a.BTID));

            var instanceDataQuery = instanceDataWhereQuery.Select((a, b, c, d) => new AnalysisInstanceResultDto
            {
                InstanceId = a.InstanceId,
                InstanceNumber = a.Number,
                InstanceTopic = a.Topic,
                InstanceStatus = b.Status,
                InstanceStatusName = b.StatusName,
                InstanceUserName = a.StartUserName,
                InstanceStartTime = b.StartTime,
                InstanceEndTime = b.LatestArriveTime,
                ProcessName = a.ProcessName,
                Status = b.Status,

                Name = c.Name,
                ArriveTime = c.ArriveTime,
                ElapsedTime = c.ElapsedTime,
                FinishTime = c.FinishTime,
                UserName = d.UserName,
                GrandNodeId = c.GrandNodeId,
                Order = c.Order,
                ActivityId = c.ActivityId,
            });

            var instanceData = await instanceDataQuery.ToListAsync();
            var instanceGroupData = instanceData.GroupBy(x => x.InstanceId).ToDictionary(x => x.Key, x => x);

            var dicList = new ConcurrentBag<Dictionary<string, object>>();
            Parallel.ForEach(instanceGroupData, new ParallelOptions() { MaxDegreeOfParallelism = 2 }, (items, _) =>
            {
                var item = new AnalysisInstanceResultDto
                {
                    ProcessName = items.Value.First().ProcessName,
                    InstanceId = items.Value.First().InstanceId,
                    InstanceNumber = items.Value.First().InstanceNumber,
                    InstanceTopic = items.Value.First().InstanceTopic,
                    InstanceStatus = items.Value.First().InstanceStatus,
                    InstanceStatusName = items.Value.First().InstanceStatusName,
                    InstanceUserName = items.Value.First().InstanceUserName,
                    InstanceStartTime = items.Value.First().InstanceStartTime,
                    InstanceEndTime = items.Value.First().InstanceEndTime,
                    NodeCount = items.Value.First().NodeCount,
                    ElapsedTime = items.Value.First().ElapsedTime,
                };
                if (item.InstanceStatus != (int)TaskCommonStatus.Done
                    && item.InstanceStatus != (int)TaskCommonStatus.Refused
                    && item.InstanceStatus != (int)TaskCommonStatus.Canceled)
                {
                    item.InstanceEndTime = null;
                }

                var activities = items.Value.OrderBy(x => x.Order).ToList()
                    .GroupBy(b => new { b.InstanceId, b.Name, b.GrandNodeId })
                    .ToDictionary(k => k.Key, v => v.ToList());

                var flag = 1;
                if (item.InstanceEndTime != null)
                {
                    item.ElapsedTime = TransferHour((item.InstanceEndTime.Value - item.InstanceStartTime.Value).TotalSeconds);
                }

                var dic = new Dictionary<string, object>(item.ToOurJsonString().ToOurObject<Dictionary<string, object>>(), StringComparer.OrdinalIgnoreCase);
                foreach (var activity in activities)
                {
                    if (activity.Key.Name == "开始")
                    {
                        continue;
                    }
                    dic.Add($"node{flag}_name", activity.Key.Name);
                    if (activity.Value.Count > 0)
                    {
                        dic.Add($"node{flag}_time", TransferHour(activity.Value.GroupBy(f => f.ActivityId)
                            .Select(f => f.First().ElapsedTime).Sum()));
                        dic.Add($"node{flag}_user", string.Join("; ", activity.Value.Select(s => s.UserName).Distinct()));

                        if (activity.Value.Any(x => x.Status == (int)InstanceQueryStatus.Processing))
                        {
                            dic.AddOrUpdate("currentNode", activity.Key.Name);
                            dic.AddOrUpdate("currentApprover", string.Join("; ", activity.Value.Select(s => s.UserName).Distinct()));
                        }
                    }

                    flag++;
                }

                if (dic.ContainsKey("nodeCount"))
                {
                    dic["nodeCount"] = flag - 1;
                }

                dicList.Add(dic);
            });

            return dicList.ToList().OrderByDescending(x => x["instanceStartTime"]).ToList();
        }

        private double? TransferHour(double? value)
        {
            if (value == null)
            {
                return null;
            }

            return Math.Round(value.Value / (60 * 60), 2);
        }

        /// <summary>
        /// 通过查询状态转为流程状态列表
        /// 修改当前方法体时请与 ConvertToInstanceStatus 对应
        /// </summary>
        /// <param name="status">查询状态</param>
        /// <returns>流程状态列表</returns>
        private static List<int> ConvertToInstnaceStatus(InstanceQueryStatus? status)
        {
            var mappedStatus = new List<TaskCommonStatus>();

            switch (status)
            {
                case InstanceQueryStatus.Ready:
                    mappedStatus.Add(TaskCommonStatus.RecallStart);
                    break;
                case InstanceQueryStatus.Start:
                    mappedStatus.Add(TaskCommonStatus.Start);
                    mappedStatus.Add(TaskCommonStatus.ReStart);
                    break;
                case InstanceQueryStatus.Processing:
                    mappedStatus.Add(TaskCommonStatus.Processing);
                    mappedStatus.Add(TaskCommonStatus.RejectActivity);
                    mappedStatus.Add(TaskCommonStatus.RejectActivityDirect);
                    mappedStatus.Add(TaskCommonStatus.Handover);
                    mappedStatus.Add(TaskCommonStatus.ExtraAppend);
                    mappedStatus.Add(TaskCommonStatus.ExtraInsert);
                    mappedStatus.Add(TaskCommonStatus.SkippedWhenEmptyResolver);
                    mappedStatus.Add(TaskCommonStatus.SkippedWhenSameApprover);
                    break;
                case InstanceQueryStatus.Approved:
                    mappedStatus.Add(TaskCommonStatus.Done);
                    break;
                case InstanceQueryStatus.Refused:
                    mappedStatus.Add(TaskCommonStatus.Refused);
                    break;
                case InstanceQueryStatus.Canceled:
                    mappedStatus.Add(TaskCommonStatus.Canceled);
                    mappedStatus.Add(TaskCommonStatus.InterveneAddNode);
                    mappedStatus.Add(TaskCommonStatus.InterveneJumpNode);
                    mappedStatus.Add(TaskCommonStatus.InterveneChangeUsers);
                    mappedStatus.Add(TaskCommonStatus.InterveneReorder);
                    mappedStatus.Add(TaskCommonStatus.InterveneRemoveNode);
                    break;
                case InstanceQueryStatus.Rejected:
                    mappedStatus.Add(TaskCommonStatus.RejectStart);
                    mappedStatus.Add(TaskCommonStatus.RejectStartDirect);
                    break;
                default:
                    break;
            }

            return mappedStatus.Select(s => (int)s).ToList();
        }

        public async Task<IWorkbook> ExportAnalysisInstances(AnalysisInstanceQueryDto input)
        {
            //if (DateTime.Now <= DateTime.Today.AddHours(17).AddMinutes(30) && DateTime.Now >= DateTime.Today.AddHours(8).AddMinutes(30))
            //{
            //    throw new Exception("只能每天早上8.30之前，下午5.30之后可以导出");
            //}

            input.IsAll = true;
            var list = await GetAnalysisInstances_All(input);
            var workbook = new XSSFWorkbook();

            if (!list.Any())
            {
                return workbook;
            }

            var columns = typeof(AnalysisInstanceResultDto)
                .GetProperties()
                .Where(x => x.CustomAttributes.Any(y => y.AttributeType == typeof(ExporterHeaderAttribute)))
                .Select(p => p.GetCustomAttributes<ExporterHeaderAttribute>().First().DisplayName).ToList();

            var maxNodeCount = list.Max(x => x.FirstOrDefault(q => q.Key == "nodeCount").Value.ObjToInt());
            for (var nodeIndex = 1; nodeIndex <= maxNodeCount; nodeIndex++)
            {
                columns.Add($"节点{nodeIndex}名称");
                columns.Add($"节点{nodeIndex}审批人");
                columns.Add($"节点{nodeIndex}审批时间(小时)");
            }

            var sheet = workbook.CreateSheet("Sheet1");
            sheet.DisplayGridlines = true;
            IRow row = sheet.CreateRow(0); // 添加表头
            IFont font1 = workbook.CreateFont();
            font1.Boldweight = (short)FontBoldWeight.Bold;
            ICellStyle style1 = workbook.CreateCellStyle();
            style1.SetFont(font1);
            style1.VerticalAlignment = NPOI.SS.UserModel.VerticalAlignment.Center;
            style1.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;
            style1.BorderBottom = BorderStyle.Thin;
            style1.BorderLeft = BorderStyle.Thin;
            style1.BorderRight = BorderStyle.Thin;
            style1.BorderTop = BorderStyle.Thin;
            for (var i = 0; i < columns.Count; i++)
            {
                sheet.SetColumnWidth(i, 15 * 256);
                row.CreateCell(i).SetCellValue(columns[i]);
                row.GetCell(i).CellStyle = style1;
            }

            for (int i = 0; i < list.Count; i++)
            {
                IRow rowtemp = sheet.CreateRow(i + 1);
                rowtemp.CreateCell(0).SetCellValue(list[i].FirstOrDefault(x => x.Key == "processName").Value?.ToString());
                rowtemp.CreateCell(1).SetCellValue(list[i].FirstOrDefault(x => x.Key == "instanceNumber").Value?.ToString());
                rowtemp.CreateCell(2).SetCellValue(list[i].FirstOrDefault(x => x.Key == "instanceTopic").Value?.ToString());
                rowtemp.CreateCell(3).SetCellValue(list[i].FirstOrDefault(x => x.Key == "instanceStatusName").Value?.ToString());
                rowtemp.CreateCell(4).SetCellValue(list[i].FirstOrDefault(x => x.Key == "instanceUserName").Value?.ToString());
                rowtemp.CreateCell(5).SetCellValue(list[i].FirstOrDefault(x => x.Key == "instanceStartTime").Value?.ToString());
                rowtemp.CreateCell(6).SetCellValue(list[i].FirstOrDefault(x => x.Key == "instanceEndTime").Value?.ToString());
                rowtemp.CreateCell(7).SetCellValue(list[i].FirstOrDefault(x => x.Key == "elapsedTime").Value?.ToString());
                rowtemp.CreateCell(8).SetCellValue(list[i].FirstOrDefault(x => x.Key == "currentNode").Value?.ToString());
                rowtemp.CreateCell(9).SetCellValue(list[i].FirstOrDefault(x => x.Key == "currentApprover").Value?.ToString());
                var index = 1;
                for (var nodeIndex = 1; nodeIndex <= maxNodeCount; nodeIndex++)
                {
                    var val1 = list[i].FirstOrDefault(x => x.Key == $"node{nodeIndex}_name").Value?.ToString();
                    var val2 = list[i].FirstOrDefault(x => x.Key == $"node{nodeIndex}_user").Value?.ToString();
                    var val3 = list[i].FirstOrDefault(x => x.Key == $"node{nodeIndex}_time").Value?.ToString();
                    rowtemp.CreateCell(9 + index).SetCellValue(val1);
                    index++;
                    rowtemp.CreateCell(9 + index).SetCellValue(val2);
                    index++;
                    rowtemp.CreateCell(9 + index).SetCellValue(val3);
                    index++;
                }
            }

            return workbook;
        }

        private async Task<bool> CheckIsAdmin()
        {
            return await _dbProcess.Queryable<Role, UserRoleMapping>((r, ur) =>
                new JoinQueryInfos(JoinType.Inner, r.Id.Equals(ur.RoleId)))
               .Where((r, ur) => ur.EmployeeCode == CurrentUser.UserName && r.IsEnable == 1 &&
               r.RoleType == (int)RoleEnum.AnalysisInstance && r.Name.ToLower().Equals("实例分析admin")).AnyAsync();
        }

        private async Task<List<string>> GetAllAuthProcessCodes()
        {
            var authProcessCodes = new List<string>();

            var userRole = await _dbProcess.Queryable<Role, UserRoleMapping>((r, ur) =>
               new JoinQueryInfos(JoinType.Inner, r.Id.Equals(ur.RoleId))).
               Where((r, ur) => r.IsEnable == 1 && (ur.EmployeeCode.Equals(CurrentUser.UserName) || r.IsPublic == 1)
               && r.RoleType == (int)RoleEnum.AnalysisInstance).Select(r => r).ToListAsync();

            if (userRole.Any())
            {
                var isAdmin = userRole.Where(r => r.Name.ToLower().Equals("实例分析admin")).Any();
                if (isAdmin)
                {
                    authProcessCodes = await _dbProcess.Queryable<AuthorizationProcessesSettings, Processes>((a, p) =>
                            new JoinQueryInfos(JoinType.Inner, a.ProcessCode.Equals(p.BTID))).
                            Where((a, p) => p.InUse == 1).Select((a, p) => p.BTID).Distinct().ToListAsync();
                }
                else
                {
                    var userRoleArray = userRole.Select(x => x.Id.ToString()).ToList();
                    authProcessCodes = await _dbProcess.Queryable<AuthorizationProcessesSettings, Processes>
                       ((a, p) => new JoinQueryInfos(JoinType.Inner, a.ProcessCode.Equals(p.BTID)))
                       .Where((a, p) => p.InUse == 1).Where((a, p) => SqlFunc.ContainsArray(userRoleArray, a.PermissionCode))
                       .Select((a, p) => p.BTID).Distinct().ToListAsync();
                }
            }

            return authProcessCodes;
        }
    }
}
